<template>
  <my-window v-loading="loadingPermissions" :title="title" :modal="modal" :wrapper-closable="true"
    :modal-append-to-body="modalAppendToBody" :visible.sync="visible" :before-close="onCancel" size="100%"
    @opened="onSearch">
    <el-table ref="multipleTable" :data="permissionTree" :default-expand-all="true"
      :tree-props="{ children: 'children', hasChildren: 'hasChildren' }" row-key="id" highlight-current-row
      style="width: 100%" @select-all="onSelectAll" @select="onSelect">
      <el-table-column type="selection" width="50" />
      <el-table-column prop="label" label="导航菜单" width="200" />
      <el-table-column label="菜单操作" width>
        <template #default="{ row }">
          <el-checkbox-group v-if="row.apis && row.apis.length > 0" v-model="chekedApis">
            <el-checkbox v-for="api in row.apis" :key="api.id" :label="api.id"
              @change="(value) => onChange(value, row.id)">{{ api.label }}</el-checkbox>
          </el-checkbox-group>
        </template>
      </el-table-column>
    </el-table>
    <template #footer>
      <el-button @click.native="onCancel">取消</el-button>
      <my-confirm-button type="submit" :loading="setPermissionLoading" @click="onSure" />
    </template>
  </my-window>
</template>

<script>
  import {
    treeToList,
    listToTree,
    getTreeParentsWithSelf
  } from "@/utils";
  import {
    getPermissions,
    getPermissionIds,
    GetTenantPermissionIds,
  } from "@/api/admin/permission";
  import MyConfirmButton from "@/components/my-confirm-button";
  import MyWindow from "@/components/my-window";

  export default {
    name: "MySelectPermission",
    components: {
      MyConfirmButton,
      MyWindow
    },
    props: {
      visible: {
        type: Boolean,
        default: false,
      },
      modal: {
        type: Boolean,
        default: false,
      },
      modalAppendToBody: {
        type: Boolean,
        default: false,
      },
      tenant: {
        type: Boolean,
        default: false,
      },
      setPermissionLoading: {
        type: Boolean,
        default: false,
      },
      roleId: {
        type: Number,
        default: 0,
      },
      tenantId: {
        type: Number,
        default: 0,
      },
      title: {
        type: String,
        default: "设置权限",
      },
    },
    data() {
      return {
        permissionTree: [],
        apis: [],
        loadingPermissions: false,
        checkedPermissions: [],
        chekedApis: [],
      };
    },
    methods: {
      // 取消
      onCancel() {
        this.chekedApis = [];
        this.checkedPermissions = [];
        this.$refs.multipleTable.clearSelection();
        this.$emit("update:visible", false);
        this.$emit("cancel");
      },
      // 确定
      onSure() {
        const permissionIds = [...this.checkedPermissions];
        if (this.chekedApis.length > 0) {
          permissionIds.push(...this.chekedApis);
        }
        this.$emit("click", permissionIds);
      },
      // 查询
      onSearch() {
        this.getPermissions();
      },
      selectApis(checked, row) {
        if (row.apis) {
          row.apis.forEach((a) => {
            const index = this.chekedApis.indexOf(a.id);
            if (checked) {
              if (index === -1) {
                this.chekedApis.push(a.id);
              }
            } else {
              if (index > -1) {
                this.chekedApis.splice(index, 1);
              }
            }
          });
        }
      },
      onSelectAll(selection) {
        const selections = treeToList(selection);
        const rows = treeToList(this.permissionTree);
        const checked = selections.length === rows.length;
        rows.forEach((row) => {
          this.$refs.multipleTable.toggleRowSelection(row, checked);
          this.selectApis(checked, row);
        });

        this.checkedPermissions = this.$refs.multipleTable.selection.map((s) => {
          return s.id;
        });
      },
      onSelect(selection, row) {
        const checked = selection.some((s) => s.id === row.id);
        if (row.children && row.children.length > 0) {
          const rows = treeToList(row.children);
          rows.forEach((r) => {
            this.$refs.multipleTable.toggleRowSelection(r, checked);
            this.selectApis(checked, r);
          });
        } else {
          this.selectApis(checked, row);
        }

        const parents = getTreeParentsWithSelf(this.permissionTree, row.id);
        parents.forEach((parent) => {
          const checked = this.checkedPermissions.includes(parent.id);
          if (!checked) {
            this.$refs.multipleTable.toggleRowSelection(parent, true);
          }
        });

        this.checkedPermissions = this.$refs.multipleTable.selection.map((s) => {
          return s.id;
        });
      },
      onChange(value, id) {
        if (value) {
          const parents = getTreeParentsWithSelf(this.permissionTree, id);
          parents.forEach((parent) => {
            const checked = this.checkedPermissions.includes(parent.id);
            if (!checked) {
              this.$refs.multipleTable.toggleRowSelection(parent, true);
            }
          });

          this.checkedPermissions = this.$refs.multipleTable.selection.map(
            (s) => {
              return s.id;
            }
          );
        }
      },
      // 获取权限树
      async getPermissions() {
        this.loadingPermissions = true;
        this.onSelectAll([]);

        const para = {};
        const res = await getPermissions(para);
        this.loadingPermissions = false;
        const tree = listToTree(_.cloneDeep(res.data));
        this.permissionTree = tree;
        this.bindPermissions();
      },
      // 绑定权限
      async bindPermissions() {
        if (
          !(
            (this.roleId != "" &&
              this.roleId != "00000000-0000-0000-0000-000000000000") ||
            (this.tenantId != "" &&
              this.tenantId != "00000000-0000-0000-0000-000000000000")
          )
        ) {
          return;
        }

        this.loadingPermissions = true;
        const para = {
          roleId: this.roleId
        };
        const res = await (this.tenant ?
          GetTenantPermissionIds({
            tenantId: this.tenantId
          }) :
          getPermissionIds(para));

        this.loadingPermissions = false;
        const permissionIds = res.data;
        const rows = treeToList(this.permissionTree);
        rows.forEach((row) => {
          const checked = permissionIds.includes(row.id);
          this.$refs.multipleTable.toggleRowSelection(row, checked);
        });
        this.checkedPermissions = this.$refs.multipleTable.selection.map((s) => {
          return s.id;
        });

        const apiIds = [];
        permissionIds.forEach((permissionId) => {
          if (!this.checkedPermissions.includes(permissionId)) {
            apiIds.push(permissionId);
          }
        });
        this.chekedApis = apiIds;
      },
    },
  };
</script>
